package net.entelijan.cobean.filesel;

import java.awt.Component;
import java.awt.Dialog;
import java.awt.FileDialog;
import java.awt.Frame;
import java.io.File;
import java.io.FilenameFilter;

import javax.swing.SwingUtilities;

import net.entelijan.cobean.core.DialogReturnValue;

public class NativeFileChooser implements IFileChooser {

	private FileDialog fileDialog;

	private File currentDirectory;

	private IFileFilter fileFilter;

	private File selectedFile;

	public NativeFileChooser() {
		super();
	}

	@Override
	public void setFileSelectionMode(FileSelectionMode fileSelectionMode) {
		if (fileSelectionMode != FileSelectionMode.FILES_ONLY) {
			throw new IllegalStateException(
					"The native file cooser support (currently) only selection mode FILES_ONLY");
		}
	}

	@Override
	public DialogReturnValue showOpenDialog(Component parent) {
		if (parent == null) {
			throw new IllegalStateException(
					"Cannot open native file dialog if the parent is null");
		}
		if (fileDialog == null) {
			FileDialog fd;
			Component root = SwingUtilities.getRoot(parent);
			if (root instanceof Frame) {
				final Frame f = (Frame) root;
				fd = new FileDialog(f);
				fd.setTitle(f.getTitle());
			} else if (root instanceof Dialog) {
				final Dialog d = (Dialog) root;
				fd = new FileDialog(d);
				fd.setTitle(d.getTitle());
			} else {
				throw new IllegalStateException(
						"The root component for the native file chooser must be a 'Frame' or a 'Dialog' but not a '"
								+ root.getClass().getName() + "'");
			}
			if (this.currentDirectory != null) {
				fd.setDirectory(this.currentDirectory.getAbsolutePath());
			}
			if (this.selectedFile != null) {
				fd.setFile(this.selectedFile.getAbsolutePath());
			}
			if (this.fileFilter != null) {
				fd.setFilenameFilter(createFilenameFilter(this.fileFilter));
			}
			this.fileDialog = fd;
		}
		fileDialog.setVisible(true);

		DialogReturnValue re;
		if (fileDialog.getFile() == null) {
			re = DialogReturnValue.CANCEL;
		} else {
			re = DialogReturnValue.OK;
		}
		return re;
	}

	private FilenameFilter createFilenameFilter(final IFileFilter fileFilter) {
		final FilenameFilter fineNameFilter = new WrappingFileFilter(fileFilter);
		return fineNameFilter;
	}

	@Override
	public File getSelectedFile() {
		if (this.fileDialog == null) {
			return null;
		} else {
			String file = this.fileDialog.getFile();
			if (file != null) {
				return new File(file);
			} else {
				return null;
			}
		}
	}

	@Override
	public void setCurrentDirectory(File currentDirectory) {
		if (this.fileDialog == null) {
			this.currentDirectory = currentDirectory;
		}
	}

	@Override
	public void setFileFilter(IFileFilter fileFilter) {
		if (this.fileDialog == null) {
			this.fileFilter = fileFilter;
		} else {
			this.fileDialog.setFilenameFilter(createFilenameFilter(fileFilter));
		}
	}

	@Override
	public void setSelectedFile(File selFile) {
		if (this.fileDialog == null) {
			this.selectedFile = selFile;
		} else {
			this.fileDialog.setFile(selFile.getAbsolutePath());
		}

	}

	private static class WrappingFileFilter implements FilenameFilter {
		private final IFileFilter fileFilter;

		private WrappingFileFilter(IFileFilter fileFilter) {
			this.fileFilter = fileFilter;
		}

		@Override
		public boolean accept(File dir, String name) {
			boolean re = true;
			if (fileFilter != null) {
				fileFilter.accept(new File(dir, name));
			}
			return re;
		}
	}

}
